#include "session_manager.hpp"
#include <random>
#include <sstream>
#include <iomanip>

SessionManager& SessionManager::getInstance() {
    static SessionManager instance;
    return instance;
}

std::string SessionManager::createSession() {
    std::string session_id = generateSessionId();
    
    std::lock_guard<std::mutex> lock(mutex_);
    sessions_[session_id] = {
        std::map<std::string, std::string>(),
        std::chrono::system_clock::now() + session_timeout_
    };
    
    return session_id;
}

std::string SessionManager::getSessionData(const std::string& session_id, const std::string& key) {
    std::lock_guard<std::mutex> lock(mutex_);
    
    auto it = sessions_.find(session_id);
    if (it == sessions_.end()) {
        return "";
    }
    
    auto& session = it->second;
    session.expiry = std::chrono::system_clock::now() + session_timeout_;
    
    auto data_it = session.data.find(key);
    if (data_it == session.data.end()) {
        return "";
    }
    
    return data_it->second;
}

void SessionManager::setSessionData(const std::string& session_id,
                                  const std::string& key,
                                  const std::string& value) {
    std::lock_guard<std::mutex> lock(mutex_);
    
    auto it = sessions_.find(session_id);
    if (it == sessions_.end()) {
        return;
    }
    
    auto& session = it->second;
    session.expiry = std::chrono::system_clock::now() + session_timeout_;
    session.data[key] = value;
}

void SessionManager::removeSession(const std::string& session_id) {
    std::lock_guard<std::mutex> lock(mutex_);
    sessions_.erase(session_id);
}

void SessionManager::cleanupExpiredSessions() {
    std::lock_guard<std::mutex> lock(mutex_);
    auto now = std::chrono::system_clock::now();
    
    for (auto it = sessions_.begin(); it != sessions_.end();) {
        if (it->second.expiry < now) {
            it = sessions_.erase(it);
        } else {
            ++it;
        }
    }
}

std::string SessionManager::generateSessionId() {
    static std::random_device rd;
    static std::mt19937 gen(rd());
    static std::uniform_int_distribution<> dis(0, 15);
    
    std::stringstream ss;
    ss << std::hex << std::setfill('0');
    
    for (int i = 0; i < 32; ++i) {
        ss << std::setw(1) << dis(gen);
    }
    
    return ss.str();
} 